home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 2 / Meeting Pearls Vol. II (1995)(GTI - Schatztruhe)[!].iso / Pearls / psion / src.doc / unsorted / opl_c / readme.txt < prev   
Text File  |  1984-10-28  |  4KB  |  139 lines

  1. CALLING C FROM OPL
  2. ==================
  3.  
  4. There are essentially three ways to call C code from OPL:
  5.  
  6.     a) Load the code into memory and execute it using the OPL keyword
  7.        USR.
  8.  
  9.     b) Build the code into a DYL (dynamic link library).  Load it
  10.        using the LibLoad OS call.  Create the objects using the
  11.        LibCreateByHandle OS call.  Then send messages to the created
  12.        objects using the LibSend OS call.
  13.  
  14.     c) Build the code into a logical device driver (LDD).  Load it
  15.        using the DevLoadLDDusing OS call.  Open a channel to the device
  16.        using the OPL keyword IOOPEN.  Execute the code using the OPL
  17.        keywords IOW and IOA.
  18.  
  19. This document describes the first method.  This is the least flexible
  20. of the three, however it is the easiest to get going.
  21.  
  22. There are two stages to the process.  First you must produce a binary
  23. file containing the code to be executed.  Then you must load the code
  24. in your OPL module and execute it.
  25.  
  26.  
  27. Producing the binary executable file
  28. ------------------------------------
  29.  
  30. It is a straightforward process to produce the binary executable.
  31. You write your C module and then compile it in the normal manner.
  32. You must then link it, but without a startup module.  Unfortunately I
  33. have not yet worked out the runes to do this using the JPI linker,
  34. however it is easy to do it using the Turbo linker, just type
  35.  
  36.     TLINK <filename>
  37.  
  38. NOTE: when you link your C program you will get a NO STACK
  39. warning, this is fine, since you stack will be provided by the OPL
  40. program (SYS$PRGO to be precise)
  41.  
  42. Finally you use EXE2BIN to convert the .EXE file to a .BIN file.
  43.  
  44. There are, however some provisos:
  45.  
  46. Firstly the procedure to be called from OPL must return with a RETF
  47. (ret far) instruction, this is accomplished using the JPI pragma:
  48.  
  49. #pragma call(seg_name=>null,near_call=>off)
  50.  
  51. Secondly, your module must not contain any static data.  That is to
  52. say any data used by you program must either be on the stack, be
  53. allocated using p_alloc(), or have been reserved for you by the
  54. calling OPL program.  Note that this also means YOU MAY NOT HAVE ANY
  55. QUOTED STRINGS (ie "Hello World").  This is because in an OPL program
  56. DS points to the OPL's data segment (the data segment of SYS$PRGO to
  57. be precise), and so any static data will be inaccessible.
  58.  
  59. Thirdly, although you know the address of the first procedure in the
  60. module, you will not know the address of any of the other procedures.
  61. I therefore suggest that, if you wish to call more than one
  62. procedure, the first procedure should contain a switch statement
  63. selecting which procedure to run:
  64.  
  65. #pragma save
  66. #pragma call(seg_name=>null,near_call=>off)
  67. GLDEF_C INT select(INT procno,INT p1,INT p2,INT p3)
  68. /*
  69. Must return with a retf (ret far), since called from OPL
  70. */
  71.     {
  72.     switch (procno)
  73.         {
  74.     case 1:
  75.         return (f1(p1,p2,p3));
  76.     case 2:
  77.         return (f2(p1,p2,p3));
  78.         }
  79.     return (-1);
  80.     }
  81. #pragma restore
  82.  
  83. Note that USR passes (up to) 4 parameters to the called code, they
  84. are in AX..DX which is where the JPI compiler expects to find them
  85. (see the reg_params pragma in OPL.C).
  86.  
  87. OPL.C is a full working example of a C program that can be called
  88. from OPL.
  89.  
  90.  
  91. Loading the binary executable from OPL
  92. --------------------------------------
  93.  
  94. There are three steps:
  95.  
  96. Firstly reserve some memory in which to load the code, this is most
  97. easily done by declaring an array of the appropriate size.
  98.  
  99. Secondly load the binary file (produced above) into this array.
  100.  
  101. Thirdly use USR to execute the code.
  102.  
  103.  
  104. All the above are illustrated in the file CALLC.OPL.
  105.  
  106.  
  107. P_STD.H
  108. -------
  109.  
  110. For those of you who do not have the Psion SDK here is an extract
  111. that should allow you to compile OPL.C
  112.  
  113. #define P_STD_H
  114. #define GLREF_D extern
  115. #define GLDEF_D
  116. #define LOCAL_D static
  117. #define GLREF_C extern
  118. #define LOCAL_C static
  119. #define GLDEF_C
  120. #define FOREVER for(;;)
  121. #define TRUE 1
  122. #define FALSE 0
  123. #define NULL 0
  124. #define VOID void
  125. #define FAST register
  126. typedef int INT,HANDLE;
  127. typedef unsigned int UINT;
  128. typedef signed char BYTE;
  129. typedef unsigned char UBYTE;
  130. typedef short int WORD;
  131. typedef unsigned short int UWORD;
  132. typedef long int LONG;
  133. typedef unsigned long int ULONG;
  134. typedef double DOUBLE;
  135. typedef float FLOAT;
  136. typedef unsigned char TEXT;
  137.  
  138. END OF DOCUMENT
  139.